package cn.itcast.dewu.service.impl;

import cn.hutool.core.lang.UUID;
import cn.itcast.dewu.dto.Result;
import cn.itcast.dewu.utils.RabbitConfirmCallbackUtil;
import cn.itcast.dewu.utils.RedisIdWork;
import cn.itcast.dewu.utils.UserHolder;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.itcast.dewu.pojo.VoucherOrder;
import cn.itcast.dewu.service.VoucherOrderService;
import cn.itcast.dewu.mapper.VoucherOrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;

import java.util.Collections;

import static cn.itcast.dewu.utils.RedisConstants.VOUCHER_LOCAK_KEY;
import static cn.itcast.dewu.utils.RedisConstants.VOUCHER_ORDER_KEY;

/**
 * @author Administrator
 * @description 针对表【tb_voucher_order】的数据库操作Service实现
 * @createDate 2022-04-29 14:06:30
 */
@Service
@Slf4j
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder>
        implements VoucherOrderService {

    @Autowired
    private RedisIdWork idWork;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    //执行lua脚本
    private static final DefaultRedisScript<Long> LUA_VOUCHER_SCRIPT;

    static {
        LUA_VOUCHER_SCRIPT = new DefaultRedisScript<>(); //获取lua脚本
        Resource resource = new ClassPathResource("voucherSkill.lua"); //获取文件的路径
        LUA_VOUCHER_SCRIPT.setLocation(resource);
        LUA_VOUCHER_SCRIPT.setResultType(long.class); //设置文件的返回类型
    }


    //秒杀的优惠券
    @Override
    public Result seckillVoucher(Long voucherId) {
        //从threadLocal中获取到userid
        Long userId = UserHolder.getUser().getId();
        //生成订单id
        long orderID = idWork.nextID(VOUCHER_ORDER_KEY+voucherId);
        //执行lua脚本
        Long result = stringRedisTemplate.execute(
                LUA_VOUCHER_SCRIPT,
                Collections.emptyList(),//这里无键,因为脚本中的键是由value值获取到的
                voucherId.toString(), userId.toString()
        );
        int value = result.intValue();
        if (value != 0) {
            return Result.fail(value == 1 ? "库存不足^_^" : "特价商品,不允许重复下单^_^");
        }
        VoucherOrder voucherOrder = new VoucherOrder();
        voucherOrder.setVoucherId(voucherId);
        voucherOrder.setUserId(userId);
        voucherOrder.setId(orderID);
        //发送到rabbitmq中
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString(true));
        correlationData.getFuture().addCallback(
                result2 -> {
                    if (result2.isAck()) {
                        log.info("消息发送成功,消息id为:{}",correlationData.getId());
                    }else{
                        log.error("消息发送到交换机失败,消息的id为:{},发送失败的原因为:{}"
                                ,correlationData.getId(),result2.getReason());
                        //重新发送消息
                        rabbitTemplate.convertAndSend("voucher.orderexchange",
                                "voucher.order",voucherOrder,correlationData);
                    }
                },
                ex->{
                    log.error("消息发送异常,消息的id为:{},发送失败的原因为:{}"
                            ,correlationData.getId(),ex.getMessage());
                    //重新发送消息
                    rabbitTemplate.convertAndSend("voucher.orderexchange",
                            "voucher.order",voucherOrder,correlationData);
                }
        );
        //发送消息
        rabbitTemplate.convertAndSend("voucher.orderexchange",
                "voucher.order",voucherOrder,correlationData);

        RabbitConfirmCallbackUtil util = new RabbitConfirmCallbackUtil();
        util.defineRabbitConfirmCallback(voucherOrder,"voucher.orderexchange","voucher.order");
        return Result.ok(voucherId);
    }

    //购买普通的优惠券
    @Override
    public Result ordinaryVoucher(Long voucherId) {
        VoucherOrder voucherOrder = new VoucherOrder();
        //从threadLocal中获取到userid
        Long userID = UserHolder.getUser().getId();
        //由id生成器转换成orderID
        long orderid = idWork.nextID("voucher:order");
        voucherOrder.setVoucherId(voucherId);
        voucherOrder.setId(orderid);
        voucherOrder.setUserId(userID);
        return Result.ok(orderid);
    }
}




